﻿#ifndef _EASY_TCP_SERVER_H_
#define _EASY_TCP_SERVER_H_

#if defined(_MSC_VER) /*&& defined(_WIN32) && defined(WIN32) && */

// SDL 关闭了也可以 除去 4996 的警告（错误）
#pragma warning(disable:4996) // #define _WINSOCK_DEPRECATED_NO_WARNINGS // The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _stricmp.
//#define _CRT_SECURE_NO_WARNINGS

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#define _WINSOCK_DEPRECATED_NO_WARNINGS
//#define FD_SETSIZE 1024   // 貌似只有 Windows 可重新定义
#include <WinSock2.h>
#include <WS2tcpip.h>

#pragma comment(lib, "ws2_32")
#include <sockhelper.h>
#else
#ifndef SOCKET_DEFINED
#define SOCKET_DEFINED
typedef int SOCKET;
#endif // !SOCKET_DEFINED

#ifndef INVALID_SOCKET
#define INVALID_SOCKET  (SOCKET)(~0)
#endif
#ifndef SOCKET_ERROR
#define SOCKET_ERROR            (-1)
#endif
//#elif defined(unix) || defined(__unix) || defined(__unix__)
////#warning You are using UNIX
//#elif defined(__APPLE__) || defined(__MACH__)
////#warning You are using Mac OS X
//#elif defined(__linux__)
////#warning You are using Linux
//#elif defined(__FreeBSD__)
////#warning You are using FreeBSD
//#else
//#error Unknown OS
#endif

#include <stdio.h>

#include <string>
#include <vector>

#include <netmsgdef.h>

// 实例对象...[
#include <textmessage.h>

// 实例对象...]

#include <XyFifo.h>



class ClientSocket
{
    SOCKET _sock;
    //XyFifo<char>* _dataBuffer;
    char* _msgBuf;
    unsigned int bufSize;
    int _lastPos;

    MessageBuildHelper _mbh;
public:
    std::string _ip;
    unsigned short port;

public:
    ClientSocket(SOCKET sock, unsigned int bufferSize) {
        _sock = sock;
        //_dataBuffer = new XyFifo<char>(bufferSize);
        _msgBuf = NULL;
        bufSize = bufferSize;
        _msgBuf = new char[bufSize];
        memset(_msgBuf, 0, bufSize);
        _lastPos = 0;
    }

    ~ClientSocket() {
        closeClient();
        if (_msgBuf)
            delete _msgBuf;
    }

    void closeClient() {
        if (INVALID_SOCKET != _sock) {
#ifdef _WIN32
            closesocket(_sock);
#else
            close(_sock);
#endif // _WIN32
        }
        _sock = INVALID_SOCKET;
    }

    SOCKET socketfd() {
        return _sock;
    }

    int getLastPos() {
        return _lastPos;
    }
    void setLastPos(int pos) {
        _lastPos = pos;
    }

    char* getBuffer() {
        return _msgBuf;
    }

    MessageBuildHelper* getMessageBuildHelper() {
        return &_mbh;
    }


    //// 读取失败返回-1, 否则返回 >= 0
    //int getData(char *data, int len) {
    //    int ret = 0;
    //    //bool suc = _dataBuffer->readData(data, (unsigned int)len);
    //    //if (!suc)
    //    //    ret = -1;
    //    return ret;
    //}


    //// 写入失败返回-1, 否则返回 >= 0
    //int appendData(const char *data, int len)
    //{
    //    int ret = 0;
    //    //bool suc = _dataBuffer->writeData(data, (unsigned int)len, true);
    //    //if (!suc)
    //    //    ret = -1;
    //    return ret;
    //}
    
};






#define SOCKET_CLIENT_BUFFER_SIZE (4096*100)




class EasyTcpServer {

    SOCKET _sock;
    std::vector<ClientSocket*> _clients;
public:
    EasyTcpServer();
    virtual ~EasyTcpServer();

    static int loadSocket();
    static void unloadSocket();
    // ---------------------------------------------------------------------

    SOCKET initSocket();
    bool isRunning();

    void closeSocket(SOCKET s);
    void closeClients();
    void closeSelf();
    void close();

    int bind(const char* ip, unsigned short port);
    int listen(int backlog = 5);


    int onRun();
    int ReceiveData(ClientSocket* pClient);
    virtual int onNetMsg(SOCKET _cSock, char* data, int dataLen);
    //virtual int onNetMsg(SOCKET _cSock, DataHead* data);

    virtual int onNetMsg(ClientSocket* pClient, DataHead* data, int bufLen);

    int sendData(SOCKET _cSock, char* data, int dataLen);
};

#ifndef _ARRAYSIZE
#define _ARRAYSIZE(a) sizeof(a)/sizeof(a[0])
#endif

#ifndef myprintf_defined
#define myprintf_defined
#define myprintf(fmt, ...) \
    Output::OutputDebugPrintf2("[< %s >] " fmt, __FUNCTION__, ##__VA_ARGS__)
#endif




#endif // !_EASY_TCP_SERVER_H_
